package com.allwees.bs.c.module.order.service.impl;

import com.allwees.bs.c.module.order.entity.OrderEntity;
import com.allwees.bs.c.module.order.entity.OrderItemEntity;
import com.allwees.bs.c.module.order.entity.OrderRefundEntity;
import com.allwees.bs.c.module.order.entity.OrderRefundItemEntity;
import com.allwees.bs.c.module.order.repository.OrderItemRepository;
import com.allwees.bs.c.module.order.repository.OrderRefundItemRepository;
import com.allwees.bs.c.module.order.repository.OrderRefundRepository;
import com.allwees.bs.c.module.order.repository.OrderRepository;
import com.allwees.bs.c.module.order.req.OrderApplyRefundReq;
import com.allwees.bs.c.module.order.service.IOrderRefundService;
import com.allwees.bs.core.model.order.wf.order.EOrderState;
import com.allwees.bs.core.model.order.wf.refund.ERefundAction;
import com.allwees.bs.core.model.order.wf.refund.ERefundState;
import com.allwees.bs.core.modelbase.constant.ResultEnum;
import com.allwees.bs.core.modelbase.exception.BusinessException;
import com.allwees.core.common.constant.EStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class OrderRefundServiceImpl implements IOrderRefundService {

    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderItemRepository orderItemRepository;
    @Autowired
    private OrderRefundRepository orderRefundRepository;
    @Autowired
    private OrderRefundItemRepository orderRefundItemRepository;

    @Override
    public void apply(OrderApplyRefundReq refundReq) {
        OrderEntity order = orderRepository.getByUuid(refundReq.getOrderUuid());
        Assert.notNull(order, "order[" + refundReq.getOrderUuid() + "] not exist");

        OrderItemEntity orderItem = orderItemRepository.getByUuid(refundReq.getOrderItemUuid());
        Assert.notNull(orderItem, "order item[" + refundReq.getOrderItemUuid() + "] not exist");

        OrderRefundEntity orderRefund = new OrderRefundEntity(refundReq, order, orderItem);
        orderRefund.setState(ERefundState.START);

        if (EOrderState.WAIT_SHIP.equals(order.getState()) || EOrderState.SHIPPING.equals(order.getState())) {
            orderRefund.signal(ERefundAction.USER_REQUEST_REFUND_ON_LIMIT);
            orderRefund.setEStatus(EStatus.OMS_REFUND);
        } else {
            orderRefund.signal(ERefundAction.USER_REQUEST_REFUND);
            orderRefund.setEStatus(EStatus.OMS_REFUNDING);
        }

        orderRefund.setOrderShippingState(refundReq.getShippingState());
        orderRefundRepository.save(orderRefund);

        OrderRefundItemEntity orderRefundItem = new OrderRefundItemEntity(orderItem);
        orderRefundItem.setOrderRefundUuid(orderRefund.getUuid());
        orderRefundItemRepository.save(orderRefundItem);
    }

    @Override
    public void cancel(String userUuid, String orderRefundUuid) {

        OrderRefundEntity orderRefund = orderRefundRepository.getOneByUuid(orderRefundUuid);
        Assert.notNull(orderRefund, "order refund [" + orderRefundUuid + "] not exist");

        OrderEntity order = orderRepository.getByUuid(orderRefund.getOrderUuid());
        Assert.notNull(order, "order [" + orderRefund.getOrderUuid() + "] not exist");

        if (!order.getUserUuid().equals(userUuid)) {
            throw BusinessException.getInstance(ResultEnum.UNAUTHORIZED);
        }

        orderRefund.signal(ERefundAction.USER_CANCEL_REFUND);
        orderRefundRepository.save(orderRefund);
    }

    @Override
    public Map<String, OrderRefundEntity> getRefunds(Set<String> orderUuids){
        if(CollectionUtils.isEmpty(orderUuids)){
            return new HashMap<>(0);
        }
        List<OrderRefundEntity> orderRefunds = orderRefundRepository.getByOrderUuids(orderUuids);
        if(CollectionUtils.isEmpty(orderRefunds)){
            return new HashMap<>(0);
        }

        return orderRefunds.stream().collect(Collectors.toMap(OrderRefundEntity::getOrderItemUuid, o -> o));
    }

    @Override
    public OrderRefundEntity getRefundByOrderItemUuid(String orderItemUuid) {
        OrderRefundItemEntity orderRefundItem = orderRefundItemRepository.getByUuid(orderItemUuid);
        if(orderRefundItem == null){
            return null;
        }
        OrderRefundEntity orderRefund = orderRefundRepository.getOneByUuid(orderRefundItem.getOrderRefundUuid());
        if(orderRefund == null){
            return null;
        }
        orderRefund.setItem(orderRefundItem);
        return orderRefund;
    }
}
